package com.linkoog.devtools.code_generator.template.render.engine.velocity;

import com.linkoog.devtools.code_generator.template.render.engine.TemplateEngine;
import com.linkoog.devtools.code_generator.template.render.engine.velocity.directive.Append;
import com.linkoog.devtools.code_generator.template.render.engine.velocity.directive.Package;
import com.linkoog.devtools.code_generator.template.render.engine.velocity.directive.GetPackage;
import com.linkoog.devtools.code_generator.template.render.engine.velocity.directive.ImportPackage;
import com.linkoog.devtools.code_generator.template.render.engine.velocity.directive.LowerCase;
import com.linkoog.devtools.code_generator.template.render.engine.velocity.directive.Split;
import com.linkoog.devtools.code_generator.template.render.engine.velocity.directive.SplitAndGetLastOne;
import com.linkoog.devtools.code_generator.template.render.engine.velocity.directive.UpperCase;
import com.intellij.codeInsight.generation.VelocityIncludesClassLoader;
import com.intellij.openapi.util.ClassLoaderUtil;
import org.apache.commons.collections.ExtendedProperties;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.VelocityEngine;
import org.apache.velocity.runtime.RuntimeConstants;

import java.io.StringWriter;
import java.util.Map;
import java.util.Properties;

public class VelocityTemplateEngine implements TemplateEngine {

    protected final static VelocityEngine VELOCITY_ENGINE = newVelocityEngine();


    private static VelocityEngine newVelocityEngine() {
        Properties prop = new Properties();
        prop.put("runtime.log.logsystem.log4j.category", "GenerateToString");
        prop.put(RuntimeConstants.RESOURCE_LOADER, "includes");
        prop.put("includes.resource.loader.class", VelocityIncludesClassLoader.class.getName());
        prop.put(RuntimeConstants.VM_PERM_ALLOW_INLINE_REPLACE_GLOBAL, "true");
        //prop.put(RuntimeConstants.RUNTIME_LOG_LOGSYSTEM_CLASS, NullLogChute.class.getName());

        VelocityEngine velocity = new VelocityEngine();

        /*
          IDEA 的 URLClassLoader 无法获取当前插件的 path
          @see org.apache.velocity.util.ClassUtils
         */
        ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
        Thread.currentThread().setContextClassLoader(VelocityTemplateEngine.class.getClassLoader());

        velocity.loadDirective(LowerCase.class.getName());
        velocity.loadDirective(UpperCase.class.getName());

        velocity.loadDirective(Append.class.getName());
        velocity.loadDirective(Split.class.getName());
        velocity.loadDirective(SplitAndGetLastOne.class.getName());

        velocity.loadDirective(Package.class.getName());
        velocity.loadDirective(ImportPackage.class.getName());
        velocity.loadDirective(GetPackage.class.getName());
        Thread.currentThread().setContextClassLoader(classLoader);

        ClassLoaderUtil.runWithClassLoader(VelocityIncludesClassLoader.class.getClassLoader(), () -> velocity.init(prop));
        return velocity;
    }

    @Override
    public String render(String templateContent, Map<String,Object> dataMap) throws Exception {
        if (templateContent == null || templateContent.trim().isEmpty()) {
            return "";
        }
        VelocityContext velocityContext = new VelocityContext(dataMap);
        StringWriter writer = new StringWriter();
        VELOCITY_ENGINE.evaluate(velocityContext, writer, "", templateContent);
        return writer.toString();
    }
}
